package top.wilbert.collegelink.message.component;/**
 * @author augus
 * @create 2023-03-23-20:30
 */


import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Augus
 * @ClassName:MsgPushServer
 * @Description:
 * @date 2023/3/23 20:30
 * @Version 1.0
 **/

public class ServerSocketDemo {
    private static java.net.ServerSocket serverSocket = null;
    private static Socket clientSocket = null;
    //客户端集合
    private static Map<String, ServerThread> serverThreadMap = new HashMap<>();

    public static void startServerSocket() {
        try {
            //建立服务端
            serverSocket = new ServerSocket(10016);
            System.out.println("server端已启动！");
            while (true) {
                //创建接收接口
                clientSocket = serverSocket.accept();
                //启动新客户监听线程
                new ServerThread(serverSocket, clientSocket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                clientSocket.close();
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 内部类线程，每连接一个新的客户端就启动一个对应的监听线程
     */
    @SuppressWarnings("Duplicates")
    private static class ServerThread extends Thread {
        ServerSocket serverSocket = null;
        Socket clientSocket = null;
        InputStream is = null;
        OutputStream os = null;
        String fromUserId = null;
        boolean alive = true;

        public ServerThread() {
        }

        ServerThread(ServerSocket serverSocket, Socket clientSocket) {
            this.serverSocket = serverSocket;
            this.clientSocket = clientSocket;
        }

        @Override
        public void run() {
            //接收数据
            try {
                is = clientSocket.getInputStream();
                //发送
                os = clientSocket.getOutputStream();
                //缓存区
                byte[] b = new byte[1024];
                int length = 0;
                while (alive) {
                    //接收从客户端发送的消息
                    length = is.read(b);
                    if (length != -1) {
                        //文本消息
                        String message = new String(b, 0, length);

                        //JSON字符串转 HashMap
                        HashMap hashMap = new ObjectMapper().readValue(message, HashMap.class);

                        //消息类型
                        String type = (String) hashMap.get("type");

                        //新连接
                        if ("OPEN".equals(type)) {
                            fromUserId = (String) hashMap.get("fromUserId");
                            //添加客户端到集合容器中
                            serverThreadMap.put(fromUserId, this);
                            System.out.println(fromUserId + "连接成功！");
                            System.out.println("当前客户端数量：" + serverThreadMap.size());
                        }

                        //关闭
                        if ("CLOSE".equals(type)) {
                            alive = false;
                            System.err.println(fromUserId + "退出连接，关闭监听线程！");
                        }

                        //文本消息
                        if ("MESSAGE".equals(type)) {
                            String msg = (String) hashMap.get("message");

                            String chat = (String) hashMap.get("chat");
                            //群聊（广播）
                            if ("GROUP".equals(chat)) {
                                //遍历容器，给容器中的每个对象转发消息
                                for (ServerThread st : serverThreadMap.values()) {
                                    //向其他客户端发送数据
                                    if (st != this) {
                                        st.os.write(new String(b, 0, length).getBytes());
                                    }
                                }

                                //后台打印
                                System.out.println(fromUserId + "向所有人说：" + msg);
                            }
                            //私聊
                            if ("PRIVATE".equals(chat)) {
                                String toUserId = (String) hashMap.get("to");
                                serverThreadMap.get(toUserId).os.write(new String(b, 0, length).getBytes());
                                //后台打印
                                System.out.println(fromUserId + "向" + toUserId + "说：" + msg);
                            }
                            //点赞
                            if ("LIKE".equals(chat)) {
                                String toUserId = (String) hashMap.get("to");
                                serverThreadMap.get(toUserId).os.write(new String(b, 0, length).getBytes());
                                //后台打印
                                System.out.println(fromUserId + "向" + toUserId + "说：" + msg);
                            }
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.err.println("与" + fromUserId + "连接中断，被迫关闭监听线程！");
            } finally {
                try {
                    serverThreadMap.remove(fromUserId);
                    System.out.println("当前客户端数量：" + serverThreadMap.size());
                    os.close();
                    is.close();
                    clientSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

//    public static void startServerSocket(int port) throws IOException {
//        java.net.ServerSocket serverSocket = new java.net.ServerSocket(port);
//        System.out.println("等待客户端连接，端口号为：" + serverSocket.getLocalPort() + "...");
//
//        while(true) {
//            // 等待客户端连接
//            Socket clientSocket = serverSocket.accept();
//            new Thread(()->{
//                try {
//
//                    System.out.println("远程主机地址：" + clientSocket.getRemoteSocketAddress());
//
//                    // 获取输入输出流
//                    DataInputStream in = new DataInputStream(clientSocket.getInputStream());
//                    DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
//
//                    // 读取客户端信息
//                    String clientMsg = in.readUTF();
//                    System.out.println("来自客户端的消息：" + clientMsg);
//
//                    String[] splitMsg = clientMsg.split(" ");
//                    String fromUserId = splitMsg[0];
//                    socketMap.put(fromUserId,clientSocket);
//
//                    if (splitMsg[1].equals("/to")) {
//                        String toUserId = splitMsg[2];
//                        Socket receiverSocket = socketMap.get(toUserId);
//                        if (receiverSocket == null) {
//                            out.writeUTF(toUserId + "不存在");
//                            out.flush();
//                        }
//
//                        String msg = splitMsg[3];
//                        DataOutputStream receiverOut = new DataOutputStream(receiverSocket.getOutputStream());
//                        receiverOut.writeUTF(fromUserId + "给你点了个赞" + msg);
//                        receiverOut.flush();
//                    } else {
//                        for (Map.Entry<String, Socket> entry : socketMap.entrySet()) {
//                            if (!entry.getKey().equals(fromUserId)) {
//                                DataOutputStream outputStream = new DataOutputStream(entry.getValue().getOutputStream());
//                                outputStream.writeUTF(fromUserId + "说：" + clientMsg);
//                                outputStream.flush();
//                            }
//                        }
//                    }
//                } catch (IOException e) {
//                    e.printStackTrace();
//                } finally {
//                    try {
//                        clientSocket.close();
//                    } catch (IOException e) {
//                        e.printStackTrace();
//                    }
//                }
//            }).start();
//
//        }
//    }
}